package com.ft.core.utils;

import com.ft.core.action.Action_2;
import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;
import org.modelmapper.PropertyMap;
import org.modelmapper.TypeMap;
import org.modelmapper.convention.MatchingStrategies;
import org.modelmapper.convention.NameTransformers;
import org.modelmapper.convention.NamingConventions;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @copyright (C), 2015-2019, 梵途科技有限公司
 * @fileName: AutoMapUtils
 * @author: 李阳
 * @date: 2019/4/17 11:20
 * @description: ModelMapper 工具类
 */
public class AutoMapUtils {

    private static final ModelMapper MODEL_MAPPER = new ModelMapper();

    static {
        MODEL_MAPPER.getConfiguration().setSourceNamingConvention(NamingConventions.JAVABEANS_ACCESSOR)
                .setDestinationNamingConvention(NamingConventions.JAVABEANS_MUTATOR)
                .setSourceNameTransformer(NameTransformers.JAVABEANS_ACCESSOR)
                .setDestinationNameTransformer(NameTransformers.JAVABEANS_MUTATOR)
                .setMatchingStrategy(MatchingStrategies.STRICT);
    }

    /**
     * 转换(只是兼容老函数重载)
     *
     * @param source      源
     * @param targetClass 目标类型
     * @return
     */
    public static <Target> Target mapTo(Class<Target> targetClass, Object source) {
        if (source == null) {
            return null;
        }
        return MODEL_MAPPER.map(source, targetClass);
    }

    /**
     * 转换
     *
     * @param source      源对象
     * @param destination 被赋值的对象
     */
    public static void map(Object source, Object destination) {
        MODEL_MAPPER.map(source, destination);
    }

    /**
     * 转换
     *
     * @param source      源
     * @param targetClass 目标类型
     * @return
     */
    public static <Target> Target map(Object source, Class<Target> targetClass) {
        if (source == null) {
            return null;
        }
        return MODEL_MAPPER.map(source, targetClass);
    }

    /**
     * 转换为列表
     *
     * @param sourceList  源列表
     * @param targetClass 目标类型
     * @return
     */
    public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass) {
        return mapList(sourceList, targetClass, null);
    }

    /**
     * 转换为列表
     *
     * @param sourceList
     * @param targetClass
     * @param setAction
     * @return
     */
    public static <TSource, Target> List<Target> mapList(Collection<TSource> sourceList, Class<Target> targetClass,
                                                         Action_2<TSource, Target> setAction) {
        List<Target> items = new ArrayList<Target>();
        if (sourceList == null) {
            return items;
        }
        Action_2<TSource, Target> act = setAction;
        if (act != null) {
            for (TSource source : sourceList) {
                Target item = map(source, targetClass);
                act.apply(source, item);
                items.add(item);
            }
        } else {
            for (TSource source : sourceList) {
                Target item = map(source, targetClass);
                items.add(item);
            }
        }
        return items;
    }

    /**
     * 转换
     *
     * @param source      源
     * @param targetClass 目标类型
     * @param typeMapName
     * @return
     */
    public <Target> Target map(Object source, Class<Target> targetClass, String typeMapName) {
        if (source == null) {
            return null;
        }
        return MODEL_MAPPER.map(source, targetClass, typeMapName);
    }

    /**
     * 添加转换
     *
     * @param converter 转换器
     */
    public static <S, D> void addConverter(Converter<S, D> converter) {
        MODEL_MAPPER.addConverter(converter);
    }

    /**
     * 添加映射
     *
     * @param propertyMap
     * @return
     */
    public <S, D> TypeMap<S, D> addMappings(PropertyMap<S, D> propertyMap) {
        return MODEL_MAPPER.addMappings(propertyMap);
    }

}

